package com.transaction.manage.service.dayEnd;

import com.transaction.common.util.DateUtil;
import com.transaction.common.util.ParamsUtil;
import com.transaction.common.util.Sid;
import com.transaction.manage.localMapper.ChannelInfoMapper;
import com.transaction.manage.model.dto.ChannelInfo;
import com.transaction.manage.model.dto.FlowInfo;
import com.transaction.manage.model.vo.HandleVo;
import com.transaction.manage.service.BusinessHandleService;
import com.transaction.manage.util.InvokeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.List;

@Service
public class HandleDataService {

    private static Logger LOGGER = LoggerFactory.getLogger(HandleDataService.class);

    @Autowired
    private ChannelInfoMapper channelInfoMapper;

    @Autowired
    private BusinessHandleService businessHandleService;

    @Autowired
    private HandleDataCheck handleDataCheck;

    //处理数据
    @Transactional(propagation = Propagation.SUPPORTS,rollbackFor = Exception.class)
    public HandleVo handleData(List<FlowInfo> flowInfoList,String channelCode,String handleDate,String flowCode){
        LOGGER.info("渠道：【{}】,日期：【{}】,开始处理日终/日启批量,开始时间:【{}】", channelCode, handleDate, LocalDate.now());
        //判断当前日期是否是交易日
        boolean isWorkDay = handleDataCheck.checkHandleDateIsWorkDate(channelCode,handleDate);
        if(!isWorkDay){
            LOGGER.info("渠道:【{}】,在：【{}】,为非交易日。",channelCode,handleDate);
            return HandleVo.error("渠道" + channelCode + "在" + handleDate + "为非交易日。");
        }

        //判断是否有在处理中的数据
        boolean isProcess = handleDataCheck.checkFlowIsProcess(flowCode,channelCode,handleDate);
        if(isProcess){
            LOGGER.info("渠道:【{}】,正在处理流程:【{}】,日期：【{}】的数据。",channelCode,flowCode,handleDate);
            return HandleVo.error("渠道" + channelCode + "正在处理" + handleDate + "的数据。");
        }

        ChannelInfo channelInfo = channelInfoMapper.selectValidChannelInfoByChannelCode(channelCode);
        if(channelInfo == null){
            LOGGER.info("渠道:【{}】,不是有效状态,请检查。",channelCode);
            return HandleVo.error("渠道" + channelCode + "不是有效状态,请检查。");
        }

        executeHandleData(flowInfoList,channelCode,channelInfo,handleDate);

        return HandleVo.ok();

    }

    /**
     * 执行处理流程步骤
     * @param flowInfoList 流程步骤
     * @param channelCode 渠道编码
     * @param channelInfo 渠道信息
     * @param handleDate 处理日期
     */
    public void executeHandleData(List<FlowInfo> flowInfoList, String channelCode, ChannelInfo channelInfo, String handleDate) {
        HandleVo retVo = HandleVo.ok();

        for (FlowInfo flowInfo : flowInfoList) {
            Integer stepCode = flowInfo.getStepCode();
            String stepName = flowInfo.getStepName();
            String packageName = flowInfo.getPackageName();
            String className = flowInfo.getClassName();
            String methodName = flowInfo.getMethodName();
            String flowName = flowInfo.getFlowName();

            //生成一个全局唯一的流程操作日志编码logCode
            String logCode = Sid.nextCode(DateUtil.FORMAT_STR_TIME14);
            LOGGER.info("渠道:【{}】,处理日期:【{}】,流程:【{}】,第【{}】个步骤,生成的日志Code:【{}】",
                    channelCode, handleDate, flowName, stepCode, logCode);
            Object[] args = new Object[]{channelInfo,handleDate,logCode,stepCode};
            try {
                //插入操作日志
                businessHandleService.insertFlowLog(logCode,channelCode,handleDate,flowInfo);
                LOGGER.info("渠道:【{}】,处理日期:【{}】,流程:【{}】,第【{}】个步骤:【{}】,开始处理,时间:【{}】",
                        channelCode, handleDate, flowName, stepCode, stepName, LocalDate.now());

                Class<?> clazz = Class.forName(packageName + "." + className);
                retVo = (HandleVo) InvokeUtil.invokeMethodByName(clazz,methodName,args);

                LOGGER.info("渠道:【{}】,处理日期:【{}】,流程:【{}】,第【{}】个步骤:【{}】,处理结束,时间:【{}】",
                        channelCode, handleDate, flowName, stepCode, stepName, LocalDate.now());
                //更新操作日志
                businessHandleService.updateFlowLog(logCode,retVo);
                if (HandleVo.ERROR_CODE.equals(retVo.getRetCode())) {
                    LOGGER.info("渠道:【{}】,处理日期:【{}】,流程:【{}】,第:【{}】步,步骤名称:【{}】,处理失败,失败原因:【{}】",
                            channelCode, handleDate, flowName, stepCode, stepName, retVo.getRetMsg());
                    break;
                }
            }catch(Exception e){
                String errorMsg = ParamsUtil.getErrorMsg(e);
                LOGGER.info("渠道:【{}】,处理日期:【{}】,流程:【{}】,方法:【{}】,处理错误,错误信息:【{}】,请联系管理员。",
                        channelCode,handleDate,flowName,"handleData",errorMsg);
                //更新操作日志
                retVo = HandleVo.error("未知异常,请【点击】查看详情。");
                businessHandleService.updateFlowLog(logCode,retVo);
                businessHandleService.asyncInsertLogDetail(logCode,errorMsg);
                break;
            }
        }
    }

}
